package com.weifly.weistock.module.stockbill.parse;

import com.weifly.weistock.core.constant.StockBillBusinessNameEnum;
import com.weifly.weistock.core.constant.StockBillColumnTypeEnum;
import com.weifly.weistock.core.util.WeistockUtils;
import com.weifly.weistock.module.stockbill.StockBillConverter;
import com.weifly.weistock.module.stockbill.bo.BillHeadColumn;
import com.weifly.weistock.module.stockbill.bo.BillParseContext;
import com.weifly.weistock.module.stockbill.bo.StockRecordBO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * 对账单分析器
 *
 * @author weifly
 * @since 2021/05/14
 */
public abstract class AbstractBillAnalyzer {

    private Logger log = LoggerFactory.getLogger(AbstractBillAnalyzer.class);

    /**
     * 分析表头
     */
    public abstract List<BillHeadColumn> analyzeHead(List<String> lineList);

    /**
     * 分析交易记录
     */
    public StockRecordBO analyzeOneRecord(BillParseContext context, String line) {
        String[] parts = line.split("\\s+");
        if (parts == null || parts.length < 2) {
            log.warn("非法行, line = " + line);
            return null;
        }

        List<BillHeadColumn> headColumnList = context.getHeadColumnList();
        StockRecordBO recordBO = new StockRecordBO();
        int valueIndex = 0;
        for (BillHeadColumn headColumn : headColumnList) {
            if (headColumn.getColumnType() == StockBillColumnTypeEnum.DATE) { // 发生日期
                String date = parts[valueIndex];
                if (StringUtils.isBlank(date)) {
                    throw new RuntimeException(errorMessage("日期列空值", headColumn, line));
                }
                recordBO.setDate(date);
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.TIME) { // 成交时间
                String time = parts[valueIndex];
                if (StringUtils.isBlank(time)) {
                    throw new RuntimeException(errorMessage("时间列空值", headColumn, line));
                }
                recordBO.setTime(time);
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.BUSINESS_NAME) { // 业务名称
                String businessName = parts[valueIndex];
                StockBillBusinessNameEnum businessNameEnum = StockBillBusinessNameEnum.getEnumByName(businessName);
                if (businessNameEnum == null) {
                    throw new RuntimeException(errorMessage("业务名称不支持: " + businessName, headColumn, line));
                }
                recordBO.setBusinessName(businessNameEnum);
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.STOCK_CODE) { // 证券代码
                String stockCode = parts[valueIndex];
                if (StringUtils.isBlank(stockCode)) {
                    throw new RuntimeException(errorMessage("证券代码空值", headColumn, line));
                }
                recordBO.setStockCode(stockCode);
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.STOCK_NAME) { // 证券名称 其中可能包含空格
                String stockName = parts[valueIndex];
                if (StringUtils.isBlank(stockName)) {
                    throw new RuntimeException(errorMessage("证券名称空值", headColumn, line));
                }
                recordBO.setStockName(stockName);
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.TRADE_PRICE) { // 成交价格
                String tradePrice = parts[valueIndex];
                if (StringUtils.isBlank(tradePrice)) {
                    throw new RuntimeException(errorMessage("成交价格空值", headColumn, line));
                }
                recordBO.setTradePrice(Double.valueOf(tradePrice));
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.TRADE_NUMBER) { // 成交数量，取绝对值
                String tradeNumber = parts[valueIndex];
                if (StringUtils.isBlank(tradeNumber)) {
                    throw new RuntimeException(errorMessage("成交数量空值", headColumn, line));
                }
                recordBO.setTradeNumber(Math.abs(Double.valueOf(tradeNumber).intValue()));
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.TRADE_AMOUNT) { // 成交金额
                String tradeAmount = parts[valueIndex];
                if (StringUtils.isBlank(tradeAmount)) {
                    throw new RuntimeException(errorMessage("成交金额空值", headColumn, line));
                }
                recordBO.setTradeAmount(Double.valueOf(tradeAmount));
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.AFTER_NUMBER) { // 股份余额
                String afterNumber = parts[valueIndex];
                if (StringUtils.isBlank(afterNumber)) {
                    throw new RuntimeException(errorMessage("股份余额空值", headColumn, line));
                }
                recordBO.setAfterNumber(Double.valueOf(afterNumber).intValue());
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.FEE_SERVICE) { // 手续费
                String feeService = parts[valueIndex];
                if (StringUtils.isBlank(feeService)) {
                    throw new RuntimeException(errorMessage("手续费空值", headColumn, line));
                }
                recordBO.setFeeService(Double.valueOf(feeService));
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.FEE_STAMP) { // 印花税
                String feeStamp = parts[valueIndex];
                if (StringUtils.isBlank(feeStamp)) {
                    throw new RuntimeException(errorMessage("印花税空值", headColumn, line));
                }
                recordBO.setFeeStamp(Double.valueOf(feeStamp));
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.FEE_TRANSFER) { // 过户费
                String feeTransfer = parts[valueIndex];
                if (StringUtils.isBlank(feeTransfer)) {
                    throw new RuntimeException(errorMessage("过户费空值", headColumn, line));
                }
                recordBO.setFeeTransfer(Double.valueOf(feeTransfer));
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.FEE_EXTRA) { // 附加费
                String feeExtra = parts[valueIndex];
                if (StringUtils.isBlank(feeExtra)) {
                    throw new RuntimeException(errorMessage("附加费空值", headColumn, line));
                }
                recordBO.setFeeExtra(Double.valueOf(feeExtra));
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.FEE_CLEAR) { // 交易所清算费
                String feeClear = parts[valueIndex];
                if (StringUtils.isBlank(feeClear)) {
                    throw new RuntimeException(errorMessage("交易所清算费空值", headColumn, line));
                }
                recordBO.setFeeClear(Double.valueOf(feeClear));
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.CLEAR_AMOUNT) { // 发生金额
                String clearAmountStr = parts[valueIndex];
                if (StringUtils.isBlank(clearAmountStr)) {
                    throw new RuntimeException(errorMessage("发生金额空值", headColumn, line));
                }
                double clearAmount = Double.valueOf(clearAmountStr);
                if (StockBillConverter.isOpenRecord(recordBO)) {
                    // 开仓操作为负值
                    clearAmount = clearAmount > 0 ? -clearAmount : clearAmount;
                } else if (StockBillConverter.isCloseRecord(recordBO)) {
                    // 平仓操作为正值
                    clearAmount = clearAmount < 0 ? -clearAmount : clearAmount;
                }
                recordBO.setClearAmount(clearAmount);
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.AFTER_AMOUNT) { // 资金本次余额
                String afterAmount = parts[valueIndex];
                if (StringUtils.isBlank(afterAmount)) {
                    throw new RuntimeException(errorMessage("资金本次余额空值", headColumn, line));
                }
                recordBO.setAfterAmount(Double.valueOf(afterAmount));
            } else if (headColumn.getColumnType() == StockBillColumnTypeEnum.ENTRUST_CODE) { // 委托编号
                String entrustCode = parts[valueIndex];
                if (StringUtils.isBlank(entrustCode)) {
                    throw new RuntimeException(errorMessage("委托编号空值", headColumn, line));
                }
                recordBO.setEntrustCode(entrustCode);
            }
            valueIndex++;
        }
        return recordBO;
    }

    private String errorMessage(String message, BillHeadColumn headColumn, String line) {
        return message + ", column=" + WeistockUtils.toJsonString(headColumn) + ", line=" + line;
    }
}
